package com.touchportfolio
{
	import com.greensock.TweenLite;
	import com.greensock.easing.*;
	import com.touchportfolio.VO.NodeVO;
	import com.touchportfolio.controller.KeyboardController;
	import com.touchportfolio.model.ApplicationModel;
	import com.touchportfolio.model.SettingsModel;
	import com.touchportfolio.view.Row;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.GraphicsBitmapFill;
	import flash.display.GraphicsTrianglePath;
	import flash.display.IGraphicsData;
	import flash.display.Sprite;
	import flash.display.Stage;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.display.TriangleCulling;
	import flash.events.Event;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.geom.Vector3D;
	
	import traer.physics.Particle;
	import traer.physics.ParticleSystem;

	public class Application extends Sprite
	{
		private var _appModel:ApplicationModel;
		private var _c:Sprite;  //container
		private var _rows:Array;
		private var _scrollYMemory:Number = 0;
		
		public function Application()
		{
			addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
		}
		
		private function onAddedToStage(e:Event):void
		{
			var settingsModel:SettingsModel = SettingsModel.getInstance();
			settingsModel.addEventListener(SettingsModel.XML_LOADED, onSettingsLoaded);
			settingsModel.loadXML();	
		}
		
		private function onSettingsLoaded(e:Event):void
		{
			
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.align = StageAlign.TOP_LEFT;
			
			// INIT CONTAINER
			_c = new Sprite();
			addChild(_c);
			
			_rows = [];
			
			// MODELS
			_appModel = ApplicationModel.getInstance();
			_appModel.stage = stage;
			_appModel.addEventListener(ApplicationModel.GRID_DATA_LOADED, onGridDataLoaded);
			_appModel.addEventListener(ApplicationModel.ACTIVE_ROW_CHANGE, onActiveRowChange);
			_appModel.addEventListener(ApplicationModel.ACTIVE_ROW_OPEN, onRowOpenHandler);
			_appModel.addEventListener(ApplicationModel.ACTIVE_ROW_CLOSE, onRowClosedHandler);
			_appModel.loadGridData();
			
			// CONTROLLERS
			var keyboardController:KeyboardController = new KeyboardController();
		}
		
		private var s:ParticleSystem = new ParticleSystem(new Vector3D(0, 0, 0), .28);
		private var repellerAttractedTo:DisplayObject = null;
		private var floats:Array = new Array();
		private var anchors:Array = new Array();
		private var repells:Array = new Array();
		private var magnet:Particle;
		private var repeller:Particle;
		
		private function onGridDataLoaded(e:Event):void
		{
			magnet = s.makeParticle(1, new Vector3D(stage.stageWidth/2, stage.stageHeight/2, 0));
			repeller = s.makeParticle(4, new Vector3D(stage.stageWidth/2, stage.stageHeight/2, 0));
			
			var row:Row;
			for(var i:uint=0; i<_appModel.nodes.length; i++)
			{
				var node:NodeVO = _appModel.nodes[i];
				row = new Row(node);
				row.x = 0;
				row.y = ((row.nodeHeight+1)*i);
				_c.addChild(row);	
				_rows.push(row);
				
				floats.push(s.makeParticle(2, new Vector3D(0, row.y, 0)));
				anchors.push(s.makeParticle(2, new Vector3D(0, row.y, 0)));
				anchors[i].makeFixed();
				s.makeSpring(anchors[i], floats[i], .3, .2, 0);
				s.makeAttraction(magnet, floats[i], 200 , 0);
				repells.push(s.makeAttraction(repeller, floats[i], -20000 , 1));
			}
			
			stage.addEventListener( Event.ENTER_FRAME, loop );
		}
		
		private function loop(e:Event):void
		{
			s.tick(1);

			magnet.position.x = _rows[_appModel.activeRow].x + (_rows[_appModel.activeRow].width/2);
			magnet.position.y = _rows[_appModel.activeRow].y + (_rows[_appModel.activeRow].height/2);
			
			for(var i:uint=0; i<_c.numChildren; i++){
				_rows[i].y = floats[i].position.y;
				
				if(i == _appModel.activeRow)
				{
					_rows[i].y -= 14;
				}
			}
			
			if(repellerAttractedTo)
			{
				repeller.position.x = repellerAttractedTo.x + (repellerAttractedTo.height);
				repeller.position.y = repellerAttractedTo.y + (repellerAttractedTo.height/7);
			}
		}
		
		private function onActiveRowChange(e:Event):void
		{
			repellerAttractedTo = _rows[_appModel.activeRow];
			_c.setChildIndex(_rows[_appModel.activeRow], _c.numChildren-1);
			
			// SCROLL DOWN IF NEEDED
			if((_c.y >= (stage.stageHeight - _c.height)) && (localToGlobal(new Point(0, _rows[_appModel.activeRow].y)).y > (stage.stageHeight - (_rows[_appModel.activeRow].nodeHeight*2))))
			{
				_c.y -= _rows[_appModel.activeRow].height;
				_scrollYMemory = _c.y;
			}
			
			// SCROLL UP IF NEEDED
			else if((_c.y < 0) && (localToGlobal(new Point(0, _rows[_appModel.activeRow].y)).y <= _rows[_appModel.activeRow].nodeHeight*3))
			{
				if(_appModel.activeRow == 0) {_c.y = 0;}
				else
				{
					_c.y += _rows[_appModel.activeRow].height;	
				}
				_scrollYMemory = _c.y;
			}
		}
		
		private function onRowOpenHandler(e:Event):void
		{
			for(var i:uint=_appModel.activeRow+1; i<_rows.length; i++)
			{
				anchors[i].position.y += (_rows[i] as Row).nodeOpenHeight - (_rows[i] as Row).nodeActiveHeight;
			}
			
			TweenLite.to(_c, .6, {delay: .4, y:-((_rows[0] as Row).nodeHeight * _appModel.activeRow), ease:Expo.easeOut});
		}
		
		private function onRowClosedHandler(e:Event):void
		{
			for(var i:uint=_appModel.activeRow+1; i<_rows.length; i++)
			{
				anchors[i].position.y -= (_rows[i] as Row).nodeOpenHeight - (_rows[i] as Row).nodeActiveHeight;
			}
			if(_appModel.activeRow == 0) _scrollYMemory = 0;
			if(_scrollYMemory > 0) _scrollYMemory = 0;
			
			TweenLite.to(_c, .6, {delay: .7, y:_scrollYMemory, ease:Expo.easeOut});
		}
		
	}
}